<?php


namespace app\api\dao;

use app\api\dao\wechat\OcrDao;
use app\api\model\BankDetail;
use app\api\model\Industry;
use app\api\model\WeChatMerchant;
use app\common\model\basic\SubMch;
use app\common\model\basic\SubMchOrg;
use App\Model\BankAddress;
use App\Model\Merchant;
use app\service\OcrService;
use Exception;
use think\facade\Db;

class WeChatZftDao
{
    private $mch_id;
    private $model;
    private $bankDetailModel;
    private $industryModel;

    const APPLYMENT_STATUS = [
        'APPLYMENT_STATE_EDITTING' => '编辑中',
        'APPLYMENT_STATE_AUDITING' => '审核中',
        'APPLYMENT_STATE_REJECTED' => '已驳回',
        'APPLYMENT_STATE_TO_BE_CONFIRMED' => '待账户验证',
        'APPLYMENT_STATE_TO_BE_SIGNED' => '待签约',
        'APPLYMENT_STATE_SIGNING' => '开通权限中',
        'APPLYMENT_STATE_FINISHED' => '已完成',
        'APPLYMENT_STATE_CANCELED' => '已作废',
    ];

    public function __construct($mch_id)
    {
        $this->mch_id = $mch_id;
        $this->model = new WeChatMerchant();
        $this->bankDetailModel = new BankDetail();
        $this->industryModel = new Industry();
    }

    protected function getModel(): WeChatMerchant
    {
        return $this->model;
    }


    protected function getBankDetailModel(): BankDetail
    {
        return $this->bankDetailModel;
    }

    protected function getIndustryModel(): Industry
    {
        return $this->industryModel;
    }

    public function getPagesLists($where, $page, $page_size, $field = '*')
    {
        $model = $this->getModel();
        $models = $model->where($where);
        $data = $models->page($page, $page_size)->field($field)->order('is_pay_account', 'desc')->order('id', 'desc')->select();
        $counts = $models->count();
        return [
            'page' => $page,
            'page_size' => $page_size,
            'total_count' => $counts,
            'total_page' => ceil($counts / $page_size),
            'data' => $data
        ];
    }

    public function getDetails($id)
    {
        $model = $this->getModel();
        $info = $model->find($id);
        if (empty($info)) {
            throw new Exception('数据不存在');
        }

        return $info;
    }

    public function getApplyStatus($value)
    {
        $dao = new IspDao();
        $error_info = [];
        $operateInfo = [];
        $applyment_id = $value['applyment_id'];
        if (empty($applyment_id)) {
            throw new Exception('进件申请单号不存在请检查');
        }
        $sp_name = isset($value['sp_name']) && !empty($value['sp_name']) ? $value['sp_name'] : 'isp';
        $applyments = $dao->applyment4subQuery(['applyment_id' => $applyment_id, 'sp_name' => $sp_name]);
        // 待签约
        if ($applyments['applyment_state'] == 'APPLYMENT_STATE_TO_BE_SIGNED') {
            $operateInfo['user_name'] = $value['contact_type'] == 66 ? $value['contact_name'] : $value['id_card_name'];
            $operateInfo['sign_url'] = $applyments['sign_url'];
            $value['status'] = WeChatMerchant::STATUS['TO_BE_SIGNED'];
        }

        // 待账户验证
        if ($applyments['applyment_state'] == 'APPLYMENT_STATE_TO_BE_CONFIRMED') {
            $operateInfo['user_name'] = $value['contact_type'] == 66 ? $value['contact_name'] : $value['id_card_name'];
            $operateInfo['sign_url'] = $applyments['sign_url'];

            $value['status'] = WeChatMerchant::STATUS['TO_BE_CONFIRMED'];
        }

        // 已驳回
        if ($applyments['applyment_state'] == 'APPLYMENT_STATE_REJECTED') {
            $error_info = $applyments['audit_detail'];

            $value['status'] = WeChatMerchant::STATUS['REJECTED'];
            $value['reason'] = json_encode($error_info);
        }
        // 已作废
        if ($applyments['applyment_state'] == 'APPLYMENT_STATE_CANCELED') {
            $value['status'] = WeChatMerchant::STATUS['CANCELED'];
        }
        // 已完成
        if ($applyments['applyment_state'] == 'APPLYMENT_STATE_FINISHED') {
            $value['status'] = WeChatMerchant::STATUS['COMPLETED'];
            $value['sub_mchid'] = $applyments['sub_mchid'];
            $counts = WeChatMerchant::where('sub_mch_id', '=', $value['sub_mch_id'])
                ->where('is_pay_account', '=', 1)
                ->count();
            if (empty($counts)) {
                $value['is_pay_account'] = 1;
            }
        }
        // 保存状态信息和返回信息
        $applymentsBody = [
            'applyment_state' => $applyments['applyment_state'],
            'applyment_state_msg' => self::APPLYMENT_STATUS[$applyments['applyment_state']],
            'rejected_reason' => $error_info,
            'operateInfo' => $operateInfo
        ];
        $value['body'] = json_encode($applymentsBody);
        $value->save();

        return $value;
    }

    /**
     * 新增进件数据
     * @param array $params
     * @return int|string
     * @throws Exception
     */
    public function add(array $params)
    {
        $model = $this->getModel();

        $params['out_request_no'] = time() . rand(111111, 999999);
        $params['create_time'] = time();
        $params['update_time'] = time();
        $params['business_time'] = json_encode([$params['business_start_time'], $params['business_end_time']]);
        $params['status'] = WeChatMerchant::STATUS['SUBMITTED'];
        $params['is_wx_mchid'] = 1;
        // 数据翻译
        $params['business_license_image'] = isset($params['business_license_image'][0]['url']) ? $params['business_license_image'][0]['url'] : '';
        $params['store_entrance_pic'] = isset($params['store_entrance_pic'][0]['url']) ? $params['store_entrance_pic'][0]['url'] : '';
        $params['indoor_pic'] = isset($params['indoor_pic'][0]['url']) ? $params['indoor_pic'][0]['url'] : '';
        $params['id_card_national_image'] = isset($params['id_card_national_image'][0]['url']) ? $params['id_card_national_image'][0]['url'] : '';
        $params['id_card_image'] = isset($params['id_card_image'][0]['url']) ? $params['id_card_image'][0]['url'] : '';
        $params['contact_id_doc_image_path'] = isset($params['contact_id_doc_image_path'][0]['url']) ? $params['contact_id_doc_image_path'][0]['url'] : '';
        $params['contact_id_doc_back_path'] = isset($params['contact_id_doc_back_path'][0]['url']) ? $params['contact_id_doc_back_path'][0]['url'] : '';
        $params['business_authorization_letter_path'] = isset($params['business_authorization_letter_path'][0]['url']) ? $params['business_authorization_letter_path'][0]['url'] : '';
        $params['industry_image'] = isset($params['industry_image'][0]['url']) ? $params['industry_image'][0]['url'] : '';
        $params['industry_code'] = isset($params['industry_code']) ? $params['industry_code'] : '';
        $params['activities_rate'] = isset($params['activities_rate']) ? $params['activities_rate'] : '0.35';
        $params['biz_sub_appid'] = isset($params['wechat_app_id']) ? $params['wechat_app_id'] : 'wx1daed48ae39d8201';
        if (strpos($params['bank_address'], '东莞市') == true) {
            $params['bank_address_code'] = "441900";
        }
        if (strpos($params['bank_address'], '中山市') == true) {
            $params['bank_address_code'] = "442000";
        }
        if (strpos($params['biz_address_name'], '东莞市') == true) {
            $params['biz_address_code'] = "441900";
        }
        if (strpos($params['biz_address_name'], '中山市') == true) {
            $params['biz_address_code'] = "442000";
        }


        // 进件操作
        $applyments = $this->applyment($params);
        $params['applyment_id'] = isset($applyments['applyment_id']) ? $applyments['applyment_id'] : '';
        unset($params['business_start_time']);
        unset($params['business_end_time']);
        unset($params['activities_rate']);
        unset($params['biz_sub_appid']);
        $id = $model->insertGetId($params);
        if (!$id) {
            throw new Exception('新增失败，请重试～');
        }
        return $id;
    }

    public function edit($id, array $params)
    {
        $info = $this->getDetails($id);
        $params['out_request_no'] = $info['out_request_no'];
        $params['update_time'] = time();
        $params['status'] = WeChatMerchant::STATUS['SUBMITTED'];
        $params['business_time'] = json_encode([$params['business_start_time'], $params['business_end_time']]);
        $params['industry_image'] = isset($params['industry_image'][0]['url']) ? $params['industry_image'][0]['url'] : '';
        $params['industry_code'] = isset($params['industry_code']) ? $params['industry_code'] : '';
        $params['activities_rate'] = isset($params['activities_rate']) ? $params['activities_rate'] : '0.35';
        $params['biz_sub_appid'] = isset($params['wechat_app_id']) ? $params['wechat_app_id'] : '';
        // 进件操作
        $applyments = $this->applyment($params);

        $params['applyment_id'] = isset($applyments['applyment_id']) ? $applyments['applyment_id'] : '';
        unset($params['business_start_time']);
        unset($params['business_end_time']);
        unset($params['activities_rate']);
        unset($params['biz_sub_appid']);
        $res = $info->save($params);
        if (!$res) {
            throw new Exception('修改失败，请重试～');
        }

        return $res;
    }

    private function applyment($params)
    {
        $dao = new IspDao();
        $applyments = $dao->applyment4sub($params);
        return $applyments;
    }

    public function orgList()
    {
        $orgList = $this->getSubMchOrgModel()->field('id,pid,name,location_id_list')->where('mch_id', $this->mch_id)->where('status', 1)->where('bind_sub_mch_id', 0)->where('pid', '<>', 0)->select()->toArray();
        $arr = [];
        foreach ($orgList as &$org) {
            unset($org['SubMchList']);
            unset($org['_links']);

            $arr[$org['pid']][$org['id']] = $org;
        }
        unset($orgList);
        // 按升序排列
        ksort($arr);

        $data = $this->orgTree(array_key_first($arr), $arr);
        return $data;
    }

    public function industryList()
    {
        $industryList = $this->getIndustryModel()->where('status', 1)->where('status', 1)->select()->toArray();

        return $industryList;
    }

    public function bankAccount($params)
    {
        $bankModel = $this->getBankDetailModel();

        $bankList = $bankModel->where('bank_name', 'like', "%{$params['name']}%")->page(0, 50)->select();

        return $bankList;
    }

    private function orgTree($index, $tree)
    {
        $trees = [];
        foreach ($tree[$index] as $key => $value) {
            if (isset($tree[$key])) {
                $value['children'] = $this->orgTree($key, $tree);
            }

            $trees[] = $value;
        }

        return $trees;
    }

    const OCR_TYPE = [
        'idCardFront' => "recognizeIdCard", // 身份证正面
        'idCardBack' => "recognizeIdCard",  // 身份证反面
        'businessLicense' => "recognizeBusinessLicense", // 营业执照
    ];

    public function imageOcrAndCode(string $imageUrl, string $type, string $wechatSpName = 'isp')
    {
        $requestData = [];
        $requestData['img_url'] = $imageUrl;
        $requestData['sp_name'] = $wechatSpName;
        logs('ocr请求参数：', $requestData);
        if (in_array($type, array_keys(self::OCR_TYPE))) {
            $ocrInfo = $this->imageOcr($requestData, $type);
            $res['ocrInfo'] = $ocrInfo;
        }
        $codeInfo = $this->imageCode($requestData);
        $res['codeInfo'] = $codeInfo;
        $res['imageUrl'] = $requestData['img_url'];
        return $res;
    }

    private function imageOcr(array $requestData, string $type): array
    {
        $dao = new OcrService();
        $function = self::OCR_TYPE[$type];
        return $dao->$function($requestData);
    }

    private function imageCode(array $requestData)
    {
        $dao = new IspDao();
        $requestData['image_url'] = $requestData['img_url'];
        // 图片编码
        $codeInfo = $dao->upload($requestData);
        $media_id = $codeInfo['media_id'] ?? '';
        if (!$media_id) {
            throw new \Exception('上传微信资源失败');
        }
        return $media_id;
    }

    public function setReceivingAccount(int $id, int $is_pay_account)
    {
        $subMchModel = $this->getSubMchModel();
        $info = $this->getDetails($id);

        if (!$info) {
            throw new Exception('该条数据不存在，请检查');
        }
        if (!$info['sub_mchid']) {
            throw new Exception('该申请单未通过，无法设置收款账户');
        }

        $isPayAccountCount = $info->where(['mch_id' => $info['mch_id'], 'sub_mch_id' => $info['sub_mch_id'], 'is_pay_account' => 1])->where('id', '<>', $info['id'])->count();
        if ($isPayAccountCount) {
            throw new Exception('该商户已存在收款账户，不允许重复设置, 如需设置收款账户，请先关闭其他收款账户');
        }
        $subMch = $subMchModel->where('id', $info['sub_mch_id'])->find();
        if (empty($subMch)) {
            throw new Exception('商户不存在');
        }

        Db::startTrans();
        try {
            $subMch['wechat_pay_sub_mch_id'] = '';
            $subMch['update_time'] = time();
            if ($is_pay_account) {
                $subMch['wechat_pay_sub_mch_id'] = $info['sub_mchid'];
                $subMch['update_time'] = time();
            }

            $info['is_pay_account'] = $is_pay_account;
            $info['update_time'] = time();

            $subMch->save() && $info->save();
            Db::commit();

            return $info;
        } catch (\Exception $exception) {
            Db::rollback();
            throw new Exception($exception->getMessage());
        }
    }

    public function getTranslate($data)
    {
        // 将数据翻译为前端适用的
        $business_time = json_decode($data['business_time'], true);
        $data['business_start_time'] = $business_time[0];
        $data['business_end_time'] = $business_time[1];
        $data['business_license_image'] = $data['business_license_image'] ? [['url' => $data['business_license_image']]] : [];
        $data['store_entrance_pic'] = $data['store_entrance_pic'] ? [['url' => $data['store_entrance_pic']]] : [];
        $data['indoor_pic'] = $data['indoor_pic'] ? [['url' => $data['indoor_pic']]] : [];
        $data['industry_image'] = $data['industry_image'] ? [['url' => $data['industry_image']]] : [];
        $data['id_card_national_image'] = $data['id_card_national_image'] ? [['url' => $data['id_card_national_image']]] : [];
        $data['id_card_image'] = $data['id_card_image'] ? [['url' => $data['id_card_image']]] : [];
        $data['contact_id_doc_image_path'] = $data['contact_id_doc_image_path'] ? [['url' => $data['contact_id_doc_image_path']]] : [];
        $data['contact_id_doc_back_path'] = $data['contact_id_doc_back_path'] ? [['url' => $data['contact_id_doc_back_path']]] : [];
        $data['business_authorization_letter_path'] = $data['business_authorization_letter_path'] ? [['url' => $data['business_authorization_letter_path']]] : [];
//        $data['create_time'] = date('Y-m-d H:i:s', $data['create_time']);
//        $data['update_time'] = date('Y-m-d H:i:s', $data['update_time']);
        $data['body'] = json_decode($data['body'], true);

        return $data;
    }
}
